package com.sh.data.engine.domain.util;

import com.google.common.collect.Lists;
import com.sh.data.engine.infrastructure.config.LogConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.buildobjects.process.ProcBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * @author : fuchen
 * @date : 2022/1/25 11:37
 */
@Slf4j
@Component
public class LogUtil {

    private static String DATA_API_LOG_PATH;

    private static String DATA_QUALITY_LOG_PATH;

    private static String INDEXLIB_LOG_PATH;
    /**
     * 实时同步
     */
    private static String ONLINE_LOG_PATH;
    /**
     * 实时计算
     */
    private static String FLINK_LOG_PATH;

    private static String IMPORT_LOG_PATH;

    @Autowired
    private LogConfig logConfig;

    public static List<String> readDataApiLog(Long apiId, int start) throws IOException {
        if (Objects.isNull(apiId)) {
            throw new IllegalArgumentException("invalid recordId " + apiId);
        }
        File file = getDataApiLogFile(apiId);
        if (!file.exists()) {
            return Lists.newArrayList();
        }
        String content = read(file.getAbsolutePath(), start);
        try (StringReader reader = new StringReader(content)) {
            return IOUtils.readLines(reader);
        }
    }

    public static List<String> readDataApiTestLog(Long apiId, int start) throws IOException {
        if (Objects.isNull(apiId)) {
            throw new IllegalArgumentException("invalid recordId " + apiId);
        }
        File file = getDataApiTestLogFile(apiId);
        if (!file.exists()) {
            return Lists.newArrayList();
        }
        String content = read(file.getAbsolutePath(), start);
        try (StringReader reader = new StringReader(content)) {
            return IOUtils.readLines(reader);
        }
    }

    public static List<String> readImportPackageLog(Long id, int start) throws IOException {
        if (Objects.isNull(id)) {
            throw new IllegalArgumentException("invalid id " + id);
        }
        File file = getImportByUUId(id);
        if (!file.exists()) {
            return Lists.newArrayList();
        }
        String content = read(file.getAbsolutePath(), start);
        try (StringReader reader = new StringReader(content)) {
            return IOUtils.readLines(reader);
        }
    }

    public static void writeDataqualityLog(Long recordId, List<String> lines) throws IOException {
        if (CollectionUtils.isEmpty(lines)) {
            return;
        }
        File file = getDataQualityLogFile(recordId);
        if (!file.exists()) {
            file.createNewFile();
        }
        FileUtils.writeLines(file, "UTF-8", lines, true);
    }

    public static void writeDataApiTestLog(Long recordId, List<String> lines) throws IOException {
        if (Objects.isNull(recordId)) {
            throw new IllegalArgumentException("invalid recordId : " + recordId);
        }
        if (CollectionUtils.isEmpty(lines)) {
            return;
        }

        File file = getDataApiTestLogFile(recordId);

        synchronized (LogUtil.class) {
            File parentDir = file.getParentFile();
            if (parentDir != null && !parentDir.exists()) {
                if (!parentDir.mkdirs()) {
                    throw new IllegalArgumentException("Failed to create directory " + parentDir);
                }
            }
            if (!file.exists()) {
                file.createNewFile();
            }
            FileUtils.writeLines(file, "UTF-8", lines, true);
        }
    }

    @PostConstruct
    public void init() {
        DATA_API_LOG_PATH = logConfig.getApiPath();
        DATA_QUALITY_LOG_PATH = logConfig.getDataQualityPath();
        INDEXLIB_LOG_PATH = logConfig.getInedxlib();
        ONLINE_LOG_PATH = logConfig.getOnline();
        FLINK_LOG_PATH = logConfig.getFlink();
        IMPORT_LOG_PATH = logConfig.getImportPath();
        for (String path :
            Arrays.asList(
                DATA_API_LOG_PATH,
                DATA_QUALITY_LOG_PATH,
                INDEXLIB_LOG_PATH,
                ONLINE_LOG_PATH,
                FLINK_LOG_PATH,
                IMPORT_LOG_PATH)) {
            if (StringUtils.isBlank(path) || "none".equalsIgnoreCase(path)) {
                continue;
            }
            File file = new File(path);
            if (!file.exists()) {
                file.mkdirs();
            }
        }
    }

    /**
     * api log
     */
    private static File getDataApiLogFile(Long recordId) {
        String fileName = recordId + ".log";
        return new File(DATA_API_LOG_PATH + IOUtils.DIR_SEPARATOR + fileName);
    }

    private static File getDataApiTestLogFile(Long recordId) {
        String fileName = recordId + ".log";
        return new File(DATA_API_LOG_PATH + IOUtils.DIR_SEPARATOR + "test",
            IOUtils.DIR_SEPARATOR + fileName);
    }

    private static File getImportByUUId(Long id) {
        String fileName = id + ".log";
        return new File(IMPORT_LOG_PATH + IOUtils.DIR_SEPARATOR + fileName);
    }

    /**
     * indexlib log
     */
    private static File getIndexlibLogFile(Long recordId) {
        String fileName = recordId + ".log";
        return new File(INDEXLIB_LOG_PATH + IOUtils.DIR_SEPARATOR + fileName);
    }

    private static File getDataApiResponseFile(Long recordId) {
        String fileName = recordId + ".rs";
        return new File(
            DATA_API_LOG_PATH + IOUtils.DIR_SEPARATOR + "test" + IOUtils.DIR_SEPARATOR + fileName);
    }

    private static File getDataQualityLogFile(Long recordId) {
        String fileName = recordId + ".log";
        return new File(DATA_QUALITY_LOG_PATH + IOUtils.DIR_SEPARATOR + fileName);
    }

    private static File getOnlineLogFile(Long recordId) {
        String fileName = recordId + ".log";
        return new File(ONLINE_LOG_PATH + IOUtils.DIR_SEPARATOR + fileName);
    }

    private static File getFlinkLogFile(Long recordId) {
        String fileName = recordId + ".log";
        return new File(FLINK_LOG_PATH + IOUtils.DIR_SEPARATOR + fileName);
    }

    public static void writeDataApiLog(Long recordId, List<String> lines) throws IOException {
        if (Objects.isNull(recordId)) {
            throw new IllegalArgumentException("invalid recordId : " + recordId);
        }
        if (CollectionUtils.isEmpty(lines)) {
            return;
        }

        File file = getDataApiLogFile(recordId);

        synchronized (LogUtil.class) {
            if (!file.exists()) {
                file.createNewFile();
            }
            FileUtils.writeLines(file, "UTF-8", lines, true);
        }
    }

    public static void writeIdexlibLog(Long recordId, List<String> lines) throws IOException {
        if (Objects.isNull(recordId)) {
            throw new IllegalArgumentException("invalid recordId : " + recordId);
        }
        if (CollectionUtils.isEmpty(lines)) {
            return;
        }

        File file = getIndexlibLogFile(recordId);

        synchronized (LogUtil.class) {
            if (!file.exists()) {
                file.createNewFile();
            }
            FileUtils.writeLines(file, "UTF-8", lines, true);
        }
    }

    public static void writeFlinkLog(Long recordId, List<String> lines) throws IOException {
        if (Objects.isNull(recordId)) {
            throw new IllegalArgumentException("invalid recordId : " + recordId);
        }
        if (CollectionUtils.isEmpty(lines)) {
            return;
        }

        File file = getFlinkLogFile(recordId);

        synchronized (LogUtil.class) {
            if (!file.exists()) {
                file.createNewFile();
            }
            FileUtils.writeLines(file, "UTF-8", lines, true);
        }
    }

    public static List<String> readFlinkLog(Long recordId, int offset) throws IOException {
        if (Objects.isNull(recordId)) {
            throw new IllegalArgumentException("invalid recordId " + recordId);
        }
        File file = getFlinkLogFile(recordId);
        if (!file.exists()) {
            return Lists.newArrayList();
        }
        String content = read(file.getAbsolutePath(), offset);
        try (StringReader reader = new StringReader(content)) {
            return IOUtils.readLines(reader);
        }
        // return content;
    }

    public static void writeOnlineLog(Long recordId, List<String> lines) throws IOException {
        if (Objects.isNull(recordId)) {
            throw new IllegalArgumentException("invalid recordId : " + recordId);
        }
        if (CollectionUtils.isEmpty(lines)) {
            return;
        }

        File file = getOnlineLogFile(recordId);
        // File file = new File("E:\\log\\" + recordId + ".log");
        synchronized (LogUtil.class) {
            if (!file.exists()) {
                file.createNewFile();
            }
            FileUtils.writeLines(file, "UTF-8", lines, true);
        }
    }

    public static String readOnlineLog(Long recordId, int offset) throws IOException {
        if (Objects.isNull(recordId)) {
            throw new IllegalArgumentException("invalid recordId " + recordId);
        }
        File file = getOnlineLogFile(recordId);
        // File file = new File("E:\\log\\" + recordId + ".log");
        if (!file.exists()) {
            return "";
        }
        String content = read(file.getAbsolutePath(), offset);
        return content;
    }

    public static String readIndexlibLog(Long recordId) throws IOException {
        if (Objects.isNull(recordId)) {
            throw new IllegalArgumentException("invalid recordId " + recordId);
        }
        File file = getIndexlibLogFile(recordId);
        if (!file.exists()) {
            return "";
        }
        String content = read(file.getAbsolutePath(), 1);
        return content;
    }

    public static void writeDataApiReponse(Long recordId, String response) throws IOException {
        if (Objects.isNull(recordId)) {
            throw new IllegalArgumentException("invalid recordId : " + recordId);
        }
        if (StringUtils.isBlank(response)) {
            return;
        }

        File file = getDataApiResponseFile(recordId);

        synchronized (LogUtil.class) {
            if (!file.exists()) {
                file.createNewFile();
            }
            FileUtils.write(file, response, "UTF-8");
        }
    }

    public static String readDataApiResponse(Long recordId) throws IOException {
        if (Objects.isNull(recordId)) {
            throw new IllegalArgumentException("invalid recordId " + recordId);
        }
        File file = getDataApiResponseFile(recordId);
        if (!file.exists()) {
            return "";
        }
        String content = read(file.getAbsolutePath(), 1);
        return content;
    }

    private static String read(String file, int startLine) {
        if (startLine == 0) {
            startLine = 1;
        }
        if (StringUtils.isBlank(file)) {
            throw new IllegalArgumentException("file is null");
        }
        if (startLine <= 0) {
            throw new IllegalArgumentException("invalid startLine " + startLine);
        }
        return ProcBuilder.run("sed", "-n", startLine + ",$p", file);
    }
}
